﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using SplendidCRM.Ext.Models;

namespace SplendidCRM.Ext.Controllers
{
    [Authorize]
    public class CallController : Controller
    {
        [HttpGet]
        public ActionResult RegisterInboundCall(RegisterInboundCallModel model)
        {
            if (!ModelState.IsValid) return HttpNotFound();

            if (model.TimeStamp == null) model.TimeStamp = DateTime.Now;

            //Search a customer
            var customerId = Db.QueryValue<Guid>(
                "select id from dbo.accounts where phone_office = @0",
                model.PhoneNumber);
            var currentUserId = Manager.Site.CurrentUserId;
            // not exist
            if (customerId == Guid.Empty)
            {
                var accountNumber = Db.QueryValue<Int64>("select max(cast(account_number as bigint)) from accounts") + 1;
                // create new customer
                customerId = Guid.NewGuid();
                Db.Insert("dbo.accounts", new
                                          {
                                              id = customerId,
                                              phone_office = model.PhoneNumber,
                                              date_entered = DateTime.Now,
                                              name = model.PhoneNumber,
                                              created_by = currentUserId,
                                              account_number = accountNumber
                                          });
            }

            // create a call
            var callId = Guid.NewGuid();

            Db.Insert("dbo.calls", new
                                   {
                                       id = callId,
                                       created_by = currentUserId,
                                       date_entered = DateTime.Now,
                                       date_start = model.TimeStamp,
                                       parent_id = customerId,
                                       direction = "inbound",
                                       parent_type = "Accounts",
                                       assigned_user_id = currentUserId,
                                       from_address = model.PhoneNumber
                                   });
            
            //Session["LattestCallId"] = callId.ToString();
            Manager.Session.LattestCallId = callId.ToString();
            Manager.Session.LattestPhoneNumber = model.PhoneNumber;
            // redirect to inbound call form
            return RedirectToAction("Inbound", new {callId});
        }

        [HttpPost]
        public ActionResult Inbound(CallInboundModel call, CustomerInboundModel customer, SelectedTopicInboundModel topic, Boolean redirect)
        {
            if (ModelState.IsValid)
            {
                var callDb = Db.QuerySingle("exec:dbo.GetCallDetailsForInboundCall", new { callId = call.Id });
                if (callDb != null)
                {
                    var startDate = (DateTime)callDb.date_start;
                    var duration = DateTime.Now - startDate;
                    var success = Db.Transaction(
                        q =>
                            {
                                // end call
                                // update call info
                                q.Update(new
                                             {
                                                 date_modified = DateTime.Now,
                                                 date_modified_utc = DateTime.Now.ToUniversalTime(),
                                                 date_end = DateTime.Now,
                                                 duration_hours = duration.Hours,
                                                 duration_minutes = duration.Minutes,
                                                 description = call.Description,
                                                 name = call.Name,
                                                 reason_id = call.Reason_Id
                                             }, "dbo.calls", id => call.Id);

                                // update customer info
                                q.Update(customer, "dbo.accounts", id => customer.Id);


                                // update topics
                                var selectedTopicId = (topic.TopicId ?? Guid.Empty) == Guid.Empty ? topic.CategoryId ?? Guid.Empty : topic.TopicId ?? Guid.Empty;
                                q.Execute("exec:dbo.RemoveAllCallTopics", call.Id);
                                if (selectedTopicId != Guid.Empty)
                                {
                                    q.Insert("dbo.callTopics", new {callId = call.Id, topicId = selectedTopicId});
                                }
                                if (call.Case_Id != Guid.Empty)
                                {
                                    q.Execute("exec:dbo.AssignInboundCallToCase", new {callId = call.Id, caseId = call.Case_Id, currentUserId = Manager.Site.CurrentUserId});
                                }
                            });
                    if (success)
                    {
                        return !redirect ? Json(true) : Request.Redirect(Mvc.Route("Home/Default"));
                    }
                }
                
            }
            return HttpNotFound();
        }

        [HttpPost]
        public ActionResult ConvertToCase(ConvertToCaseModel model)
        {
            if (ModelState.IsValid)
            {
                var caseId = Guid.NewGuid();
                try
                {
                    Db.Execute("exec:dbo.ConvertInboundCallToCase", model, new { currentUserId = Manager.Site.CurrentUserId, caseId });
                    return Json(new { caseId, caseName = model.Subject, success = true });
                    //return Request.Open(Mvc.Route("Cases/Edit", new {id = caseId}), parameters: new {caseId, caseName = model.Subject, success = true});
                }
                catch (Exception ex)
                {
                    return Mvc.ModelResult(new {error = ex.Message});
                }
            }
            return HttpNotFound();
        }

        [HttpPost]
        public ActionResult SaveCaseDetails(CaseDetailsModel model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    Db.Execute("exec:dbo.SaveCaseDetails", model, new { currentUserId = Manager.Site.CurrentUserId });
                    return Json(new
                                    {
                                        caseId = model.CaseId,
                                        subject = model.Subject,
                                        priority = model.Priority,
                                        status = model.Status,
                                        description = model.Description,
                                        success = true
                                    });
                }
                catch (Exception ex)
                {
                    return Mvc.ModelResult(new { error = ex.Message });
                }
            }
            return HttpNotFound();
        }

        [HttpGet]
        public ActionResult CaseDetails(Guid id, Boolean convertToCase)
        {
            if (!convertToCase)
            {
                var caseDetails = Db.QuerySingle("exec:dbo.GetCaseDetails", new { caseId = id });
                if (caseDetails == null) return HttpNotFound();
                return View(new CaseDetailsViewModel
                {
                    ConvertToCase = false,
                    AssignedUserName = caseDetails.assigned_to ?? String.Empty,
                    AssignedUserId = caseDetails.assigned_user_id ?? Guid.Empty,
                    CaseId = id,
                    AccountId = caseDetails.parent_id ?? Guid.Empty,
                    AccountName = caseDetails.parent_name ?? String.Empty,
                    Description = caseDetails.description ?? String.Empty,
                    Priority = caseDetails.priority ?? String.Empty,
                    Status = caseDetails.status ?? String.Empty,
                    Subject = caseDetails.name ?? String.Empty,
                    PriorityList = new Dictionary<String, String>
                                                 {
                                                     {"P1", "High"},
                                                     {"P2", "Medium"},
                                                     {"P3", "Low"}
                                                 }.ToObjectList(),
                    StatusList = new Dictionary<String, String>
                                                   {
                                                       {"New", "New"},
                                                       {"Assigned", "Assigned"},
                                                       {"Closed", "Closed"},
                                                       {"Pending Input", "Pending Input"},
                                                       {"Rejected", "Rejected"},
                                                       {"Duplicate", "Duplicate"}
                                                   }.ToObjectList()
                });
            }
            var call = Db.QuerySingle("exec:dbo.GetCallDetailsForInboundCall", new { callId = id });
            if (call == null) return HttpNotFound();
            return View(new CaseDetailsViewModel
                            {
                                ConvertToCase = true,
                                AssignedUserName = call.assigned_to,
                                AssignedUserId = call.assigned_user_id,
                                CallId = id,
                                AccountId = call.parent_id,
                                AccountName = call.parent_name,
                                Description = call.description,
                                Priority = "P3",
                                Status = "New",
                                Subject = call.name,
                                PriorityList = new Dictionary<String, String>
                                                 {
                                                     {"P1", "High"},
                                                     {"P2", "Medium"},
                                                     {"P3", "Low"}
                                                 }.ToObjectList(),
                                StatusList = new Dictionary<String, String>
                                                   {
                                                       {"New", "New"},
                                                       {"Assigned", "Assigned"},
                                                       {"Closed", "Closed"},
                                                       {"Pending Input", "Pending Input"},
                                                       {"Rejected", "Rejected"},
                                                       {"Duplicate", "Duplicate"}
                                                   }.ToObjectList()
                            });
        }

        [HttpGet]
        public ActionResult GetChildTopics(Guid parentTopicId)
        {
            return View(Db.Query("exec:GetChildTopicsByParentId", parentTopicId));
        }

        [HttpGet]
        [IframeWrapping]
        public ActionResult Inbound(Guid callId)
        {
            if (!ModelState.IsValid) return HttpNotFound();

            // get call info
            var call = Db.QuerySingle("exec:dbo.GetCallDetailsForInboundCall", new {callId});
            if (call == null) return HttpNotFound();

            // get customer info
            var customer = Db.QuerySingle("exec:dbo.GetCustomerDetailsForInboundCall", new {customerId = call.parent_id});
            if (customer == null) return HttpNotFound();

            // get all topics
            var selectedTopic = Db.QuerySingle("exec:dbo.GetFirstCallTopic", callId);
            var selectedCategoryId = Guid.Empty;
            var selectedTopicId = Guid.Empty;
            if (selectedTopic != null)
            {
                selectedTopicId = selectedTopic.topicId;
                selectedCategoryId = selectedTopic.categoryId;
                if (selectedCategoryId == Guid.Empty)
                {
                    selectedCategoryId = selectedTopicId;
                    selectedTopicId = Guid.Empty;
                }
            }
            call.REASONS = Db.Query("exec:GetAllReasons");
            call.CATEGORY_ID = selectedCategoryId;
            call.TOPIC_ID = selectedTopicId;
            call.CATEGORIES = Db.Query("exec:dbo.GetRootTopics");
            var parentIsCase = String.Compare(Mvc.To<String>(call.parent_type), "cases", true) == 0;
            call.CASE_ID = parentIsCase ? call.parent_id ?? Guid.Empty : Guid.Empty;
            call.CASE_NAME = parentIsCase ? call.parent_name ?? String.Empty : String.Empty;
            call.IS_NEW_CASE = false;

            var callInboundViewModel = new CallInboundViewModel
            {
                PriorityList = new Dictionary<String, String>
                {
                    {"P1", "High"},
                    {"P2", "Medium"},
                    {"P3", "Low"}
                },
                Call = call,
                Customer = customer,
                CallHistory =
                    Db.Query("exec:GetCallHistoryForInboundCall", new {phoneNumber = call.from_address, callId})
            };

            // Get Info from external web services
            string phoneNumber = customer.PHONE_OFFICE;
            if  (!string.IsNullOrWhiteSpace(phoneNumber))
            {
                GetCallInfoFromExternalService(phoneNumber,callInboundViewModel);
            }


            return View(callInboundViewModel);
        }

        private void GetCallInfoFromExternalService(string phoneNumber, CallInboundViewModel callInboundViewModel)
        {
            var service = new CCBackendService.Service();

            var result = service.IntegrationEnquiry(phoneNumber);
            
            var subcriberInfo = new SubcriberBasicInfo()
            {
                PhoneNumber = phoneNumber,
                MainProduct = result.SubscriberInfo.Subscriber.MainProductID,
                LifeCycleStatus = result.SubscriberState.LifeCycleState.HasValue? Enum.GetName(typeof(LifeCycleStateTypes),result.SubscriberState.LifeCycleState.Value) : string.Empty,
                ActiveExpiryDate = ConvertToDateTime(result.SubscriberState.ActiveStop),
                SuspendExpiryDate = ConvertToDateTime(result.SubscriberState.SuspendStop),
                DisableExpiryDate = ConvertToDateTime(result.SubscriberState.DisableStop),
                FraudState = result.SubscriberState.FraudState.HasValue ? Enum.GetName(typeof(FraudStateTypes), result.SubscriberState.FraudState.Value) : string.Empty,
                FirstActiveDate = ConvertToDateTime(result.SubscriberState.FirstActiveDate)
            };

            var balanceInfo = new BalanceInfo();
            var balanceWithAmountInfo = result.BalanceRecordList.First(b => b.BalanceDesc.Equals("Balance"));
            if (balanceWithAmountInfo!=null)
            {
                balanceInfo.Amount = balanceWithAmountInfo.Balance;
                balanceInfo.ExpirationTime = ConvertToDateTime(balanceWithAmountInfo.ExpireTime);
            }


            

            var basicInfo = service.QueryBasicInfo(phoneNumber);
            var productList = basicInfo.Subscriber.Product;
            var viewModelProductList = productList.ToList().Select(p => new ProductPackageVasService()
            {
                Name = p.Name,
                EffectiveTime = ConvertToDateTime(p.EffectiveDate),
                RentCycleEndTime = ConvertToDateTime(p.CurCycleEndTime),
                RentCycleStartTime = ConvertToDateTime(p.CurCycleStartTime),
                RentStatus = Enum.GetName(typeof (BillStatusTypes), p.BillStatus)
            }).ToList();

            callInboundViewModel.SubcriberBasicInfo = subcriberInfo;
            callInboundViewModel.BalanceInfo = balanceInfo;
            callInboundViewModel.ProductList = viewModelProductList;
        }

        private DateTime? ConvertToDateTime(string dateTimeString)
        {
            if (string.IsNullOrWhiteSpace(dateTimeString)) return null;
            var formatDateTime = dateTimeString.Length == 8 ? "yyyyMMdd" : "yyyyMMddHHmmss";
            return DateTime.ParseExact(dateTimeString, formatDateTime, null);
        }

        
    }
}
